package com.ys.service.base.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.base.*;
import com.ys.entity.business.TbBaseInfo;
import com.ys.entity.finance.TcwAccountCountForCompany;
import com.ys.entity.finance.TcwAccountDetailedForCompany;
import com.ys.entity.finance.TcwOperateFrozenRunning;
import com.ys.entity.finance.TcwFinancialTransactionTypeItem;
import com.ys.entity.flow.YspModel;
import com.ys.entity.purchase.TcgPurchasePayment;
import com.ys.entity.sys.TsUserChange;
import com.ys.entity.sys.YsCol;
import com.ys.entity.sys.YsMenu;
import com.ys.entity.sys.YsProcInst;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.enume.finance.TcwOperateFrozenRunningEnum;
import com.ys.enume.finance.TcwFinancialTransactionFlowEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.base.*;
import com.ys.mapper.business.DiySqlMapper;
import com.ys.service.base.TbPayrollSlipService;
import com.ys.service.finance.TcwFinancialTransactionFlowService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.CheckUtil;
import com.ys.util.RandomUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("tbPayrollSlipService")
public class TbPayrollSlipServiceImpl implements TbPayrollSlipService {

    @Autowired
    private TbPayrollSlipMapper tbPayrollSlipMapper;

    @Autowired
    private TbPayrollSlipItemMapper tbPayrollSlipItemMapper;

    @Autowired
    private CheckUtil checkUtil;

    @Autowired
    private YspTaskService yspTaskService;

    @Autowired
    private DiySqlMapper diySqlMapper;

    @Autowired
    private TbUserPaySlipMapper tbUserPaySlipMapper;

    @Autowired
    private TcwFinancialTransactionFlowService tcwFinancialTransactionFlowService;




    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R add(Map<String, Object> params, String subData) throws Exception {
        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TbPayrollSlip tbPayrollSlip = JSON.parseObject(JSON.toJSONString(params), TbPayrollSlip.class);
        if (new TbPayrollSlip().setBid(tbPayrollSlip.getBid()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }

        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }
        String loginUserId = ShiroUtils.getUserId();
        TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();

        tbPayrollSlip.setStatus(0);
        tbPayrollSlip.setCreateChangeId(String.valueOf(tsUserChange.getId()));
        tbPayrollSlip.setEffectStock(FlowEnum.EffectStock.NOT_EFFECT.value);
        tbPayrollSlipMapper.insert(tbPayrollSlip);
        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            TbPayrollSlipItem tbPayrollSlipItem = JSON.parseObject(JSON.toJSONString(detailJO), TbPayrollSlipItem.class);
            tbPayrollSlipItem.setUserPayApplyItemId(tbPayrollSlipItem.getId());
            tbPayrollSlipItem.setPayrollSlipBid(tbPayrollSlip.getBid());
            if(detailJO.get("vgsbm") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("运营公司不能为空,不允许保存!");
            }
            if(detailJO.get("ygvyhzh") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("收款人信息不能为空,不允许保存!");
            }
            if(detailJO.get("vbzzj") != null){
                tbPayrollSlipItem.setVbz(detailJO.get("vbzzj").toString());
            }
            tbPayrollSlipItemMapper.insert(tbPayrollSlipItem);
        }


        YsMenu ysMenu = new YsMenu().setId(MenuId.TB_PayrollSlip).queryFirst();
        if (ysMenu.getFlowModelId().longValue() != 0L) {
            YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
            String codeModel = yspModel.getCode();
            String createUserId = ShiroUtils.getUserId();
            yspTaskService.init(codeModel, tbPayrollSlip.getBid(), createUserId);
            yspTaskService.setOtherParams(tbPayrollSlip.getBid(),tbPayrollSlip.getVbz(),params.get("orgName"));
        }

        return R.ok(AddDto.gotoEdit("/web/base/tbPayrollSlip/toEdit?bid=" + tbPayrollSlip.getBid()));
    }

    /**
     * 修改员工工资申请
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R edit(Map<String, Object> params,String subData) throws Exception {

        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TbPayrollSlip tbPayrollSlip = JSON.parseObject(JSON.toJSONString(params), TbPayrollSlip.class);
        if (new TbPayrollSlip().setBid(tbPayrollSlip.getBid()).where("A.id != " + tbPayrollSlip.getId()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }

        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }

        //判断是否实在制单中
        Integer flowState = yspTaskService.flowState(tbPayrollSlip.getBid());

        if (flowState != 0){
            return R.error("员工工资申请单不是制单中,不允许保存!");
        }
        tbPayrollSlipMapper.update(tbPayrollSlip);

        //批量删除
        diySqlMapper.deleteTbPayrollSlipItemBid(tbPayrollSlip.getBid());

        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            TbPayrollSlipItem tbPayrollSlipItem = JSON.parseObject(JSON.toJSONString(detailJO), TbPayrollSlipItem.class);
            tbPayrollSlipItem.setUserPayApplyItemId(Long.valueOf(detailJO.get("userPayApplyItemId").toString()));
            tbPayrollSlipItem.setPayrollSlipBid(tbPayrollSlip.getBid());
            if(detailJO.get("vgsbm") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("运营公司不能为空,不允许保存!");
            }
            if(detailJO.get("ygvyhzh") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("收款人信息不能为空,不允许保存!");
            }
            if(detailJO.get("vbzzj") != null){
                tbPayrollSlipItem.setVbz(detailJO.get("vbzzj").toString());
            }
            tbPayrollSlipItemMapper.insert(tbPayrollSlipItem);
        }

        yspTaskService.setOtherParams(tbPayrollSlip.getBid(),tbPayrollSlip.getVbz(),params.get("orgName"));

        return R.ok(AddDto.gotoEdit("/web/base/tbPayrollSlip/toEdit?bid=" + tbPayrollSlip.getBid()));
    }

    /**
     * 删除
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R delete(Long id) {
        try {
            TbPayrollSlip tbPayrollSlip = new TbPayrollSlip().setId(id).queryFirst();
            if (tbPayrollSlip == null){
                return R.error("工资付款单不存在!");
            }

            //判断是否实在制单中
            Integer flowState = yspTaskService.flowState(tbPayrollSlip.getBid());

            if (flowState != 0){
                return R.error("工资付款单不是制单中,不允许保存!");
            }
            tbPayrollSlipMapper.deleteTrue(id);

            //批量删除
            diySqlMapper.deleteTbPayrollSlipItemBid(tbPayrollSlip.getBid());
            //删除任务
            yspTaskService.flowDelete(tbPayrollSlip.getBid(),tbPayrollSlip.getCreateChangeId());
        } catch (Exception e) {
            return R.error("删除失败!");
        }
        return R.ok("删除成功!");
    }

    /**
     * 流转
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowPass(Long id, String loginUserId) throws Exception {
        TbPayrollSlip entity = new TbPayrollSlip().setId(id).queryFirst();
        if (entity == null){
            return R.error("单据不存在,核实后再操作!");
        }
        String bid = entity.getBid();
        try {
            Flow f = yspTaskService.flowPass(bid, loginUserId);
            if (f.getCode() == Flow.Code.FAILED.value) {
                return R.error(f.getMsg());
            } else {

                if (f.getState() == Flow.State.FINISH.value) {
                    R r = flowFinish(entity);
                    if (r.getCode() == 1) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return R.error(r.getMsg());
                    }
                }
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error("服务器正在开小差，请联系客服");
        }
    }


    /**
     * 驳回
     * @param id
     * @param reason
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowRefuse(Long id, String reason, String loginUserId) throws Exception {
        try {
            TbPayrollSlip entity = new TbPayrollSlip().setId(id).queryFirst();
            String bid = entity.getBid();
            R r = yspTaskService.flowRefuse(bid, reason, loginUserId);
            if (r.getCode() == 1){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error(r.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error("服务器正在开小差，请联系客服");
        }
        return R.ok();
    }

    /**
     * 驳回
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowInit(Long id,String reason,String userId) throws Exception {
        TbPayrollSlip entity = new TbPayrollSlip().setId(id).queryFirst();
        String bid = entity.getBid();
        try {
            R r = yspTaskService.flowInit(bid, reason, userId);
            if (r.getCode() == 1){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error(r.getMsg());
            }
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    private String yzMsg(Map<String, Object> infoMap){
        //验证导入字段
        String backMsg = "";
        //获取pc字段数据
        List<YsCol> listField = new YsCol()
                .where("A.MenuId = "+ MenuId.TB_PayrollSlip)
                .setOrderby("A.SortNo ASC")
                .queryList();
        //验证必填字段的非空；其他字段的长度限制、类型
        try {
            backMsg = checkUtil.checkTableColLengthAndDataType(
                    "TB_PayrollSlip",
                    listField,
                    infoMap,
                    ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1
            );
            if(backMsg!=null && !"".equals(backMsg)){//若有误，则跳过这条信息
                return backMsg;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public R flowFinish(TbPayrollSlip entity) throws Exception {
        Date date = new Date();
        entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);


        //查询子件信息
        List<Map<String,Object>> sonlist = new TbPayrollSlipItem()
                .setPayrollSlipBid(entity.getBid())
                .addLeftJoin("TB_UserPayApplyItem upai ON upai.id = A.UserPayApplyItemId")//员工申请表详情
                .addLeftJoin("TB_UserPaySlip R ON R.id = upai.UserPaySlipidid")//员工工资表
                .addField("R.realityPaySlip AS realityPaySlip,R.id AS userPaySlipidid")//实发工资

                .addLeftJoin("TS_UserInfo U ON U.UserId = R.UserId")//用户信息表
                .addField("U.UserId AS userId")//工号
                .addField(" U.UserName AS userName")//姓名

                .addLeftJoin("TS_OrganizationInfo O ON O.OrgId = R.OrgId")//组织机构表
                .addField("O.OrgName AS orgName")//所属公司
                .addLeftJoin("TS_OrganizationAccount oa ON oa.OrgId = U.DeptId")//部门绑定账号
                .addLeftJoin("THR_OperateCompanyApply THRO ON  THRO.Vgsbm = oa.Vgsbm")
                .addField("oa.Vgsbm AS vgsbm,THRO.vgsjc AS vgsjc")//运营公司

                .addLeftJoin("TS_UserBankInfo ubi ON  ubi.UserId = R.UserId")
                .addField("ubi.vyhzh AS ygvyhzh,ubi.vkhh AS ygvkhh,ubi.vyhzhmc AS ygvyhzhmc")//收款信息


                .queryMap();

        //获取业务交易类型信息
        String transactionTypeStr =  TransactionTypeEnum.FinanceType.TB_PayrollSlip.name;;
        TbBaseInfo transactionTypeItem = tcwFinancialTransactionFlowService.getTransactionType(transactionTypeStr);

        for (Map<String,Object> son : sonlist){
            if (son.get("vgsbm") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("运营公司不存在,核实后再操作!");
            }
            //将工资条状态修改为待发放
            TbUserPaySlip tbUserPaySlip = new TbUserPaySlip().setId(Long.valueOf(son.get("userPaySlipidid").toString()));
            tbUserPaySlip.setSlipStatus(3);//工资状态（0空、1个税已导入、2待发放、3已发放）
            tbUserPaySlipMapper.update(tbUserPaySlip);


            //运营公司流水
            TcwAccountDetailedForCompany tcwAccountDetailedForCompany = new TcwAccountDetailedForCompany();
            tcwAccountDetailedForCompany.setGuid(RandomUtil.getGUID());
            tcwAccountDetailedForCompany.setVgsbm(son.get("vgsbm").toString());
            tcwAccountDetailedForCompany.setVgsjc(son.get("vgsjc").toString());
            tcwAccountDetailedForCompany.setVgsbmp(son.get("userId").toString());
            tcwAccountDetailedForCompany.setVgsjcp(son.get("userName").toString());
            tcwAccountDetailedForCompany.setVjylx(transactionTypeStr);
            tcwAccountDetailedForCompany.setFje(new BigDecimal(son.get("realityPaySlip").toString()).negate());
            tcwAccountDetailedForCompany.setDjysj(entity.getCreateTime());
            tcwAccountDetailedForCompany.setDshsj(date);
            tcwAccountDetailedForCompany.setWriteTime(date);
            tcwAccountDetailedForCompany.setVbz("工资付款单:"+entity.getBid() + "，收款人名称:" + son.get("ygvyhzhmc").toString()
                    +",收款人开户行: " + son.get("ygvkhh").toString() +",收款人账号:"+ son.get("ygvyhzh").toString() );
            diySqlMapper.insertTcwAccountDetailedForCompany(tcwAccountDetailedForCompany);

            //财务交易流水
            if(transactionTypeItem!=null && transactionTypeItem.getId()!=null){
                R res = tcwFinancialTransactionFlowService.add(false, entity.getCompanyBankId(), transactionTypeItem.getBid(),
                        son.get("ygvyhzhmc").toString(), son.get("ygvkhh").toString(), son.get("ygvyhzh").toString(), new BigDecimal(son.get("realityPaySlip").toString()).negate(),
                        entity.getCreateTime(),date,new Date(),"工资付款单："+entity.getBid()+"，备注："+(son.get("vbz")!=null?son.get("vbz").toString():""),
                        TcwFinancialTransactionFlowEnum.FromType.TB_PayrollSlipItem.value,Long.parseLong(son.get("id").toString()));
                if(res.getCode().equals( R.Code.FAILED.value)){
                    return R.error(res.getMsg());
                }
            }


        }

        tbPayrollSlipMapper.update(entity);

        return R.ok();
    }



    //获取列表数据
    @Override
    @Transactional
    public Map<String,Object> getExtraParam( String bid) throws Exception{
        Map<String,Object> entity = new TbPayrollSlip().setBid(bid)
                .addLeftJoin("YS_ProcInst Ysp ON Ysp.bid = A.bid")//流程表
                .addField("Ysp.updateTime AS updateTime1")
                .addLeftJoin("TB_UserPayApply tbup ON tbup.id = A.UserPayApplyId")//申请表
                .addLeftJoin("TS_OrganizationInfo O ON O.OrgId = tbup.OrgId")//组织机构表
                .addField("O.OrgName AS orgName")//所属公司
                .addField("tbup.bid AS userPayApplyBid")
                .addLeftJoin("TB_CompanyBankInfo cbi ON cbi.id = A.CompanyBankId")//公司银行信息
                .addField("cbi.Vyhzh AS vyhzh,cbi.Vkhh AS vkhh,cbi.Vyhzhmc AS vyhzhmc")
                .queryFirstMap();
        BigDecimal realityPaySlip = BigDecimal.ZERO;
        List<Map<String, Object>> sonlist =getItemList(  bid);
        for (Map<String, Object> son : sonlist){
            realityPaySlip = realityPaySlip.add(new BigDecimal(son.get("realityPaySlip").toString()));
        }
        entity.put("realityPaySlip",realityPaySlip);
        return entity;
    }
    //获取子列表数据
    @Override
    @Transactional
    public List<Map<String, Object>> getItemList( String bid) throws Exception{
        List<Map<String, Object>> sonlist = new TbPayrollSlipItem()
                .setPayrollSlipBid(bid)
                .addField("A.vbz AS vbzzj")//详情备注
                .addLeftJoin("TB_UserPayApplyItem upai ON upai.id = A.UserPayApplyItemId")//员工申请表详情
                .addLeftJoin("TB_UserPaySlip R ON R.id = upai.UserPaySlipidid")//员工工资表
                .addField("R.pointMonth AS pointMonth")//发薪月份
                .addField("SUBSTRING(CONVERT(varchar, DATEADD(MONTH,1,R.pointMonth + '-01'), 23),0,8) AS payDate")//发薪年月
                .addField("R.wagesPay AS wagesPay")//应发工资
                .addField("R.needPaySlip AS needPaySlip")//应付工资
                .addField("R.personalTax AS personalTax")//个人所得税
                .addField("R.realityPaySlip AS realityPaySlip")//实发工资

                .addLeftJoin("TS_UserInfo U ON U.UserId = R.UserId")//用户信息表
                .addField("(U.UserId + '/' + U.UserName) AS userName")//工号/姓名
                .addLeftJoin("TS_OrganizationInfo oi ON oi.OrgId = U.DeptId")//组织机构表
                .addField("oi.OrgName AS deptName")//部门

                .addLeftJoin("THR_UserArchives UAS ON UAS.UserId = R.UserId")//用户档案表
                .addField("UAS.UserState AS userState")//员工状态

                .addLeftJoin("TS_OrganizationInfo O ON O.OrgId = R.OrgId")//组织机构表
                .addField("O.OrgName AS orgName")//所属公司
                .addLeftJoin("TS_OrganizationAccount oa ON oa.OrgId = U.DeptId")//部门绑定账号
                .addLeftJoin("THR_OperateCompanyApply THRO ON  THRO.Vgsbm = oa.Vgsbm")
                .addField("oa.Vgsbm AS vgsbm,THRO.vgsjc AS vgsjc")//运营公司

                .addLeftJoin("TS_UserBankInfo ubi ON  ubi.UserId = U.UserId")
                .addField("ubi.vyhzh AS ygvyhzh,ubi.vkhh AS ygvkhh,ubi.vyhzhmc AS ygvyhzhmc")//收款信息

                .addLeftJoin("TB_UserMonthPerformance MP ON MP.Id = R.MonthPerformanceId")//员工月度绩效信息表
                .addField("MP.Rank AS rank")//岗位职级
                .addField("MP.Type AS type")//岗位工种(0总经理 1副总经理 2责任月薪型员工 3绩效提奖型员工 4研发人员)

                .addLeftJoin("TB_JobLevel JB ON JB.Id = R.RoleLevelId")//岗位职级管理表
                .addField("JB.Category AS category")//岗位类别
                .addField("JB.Categories AS categories")//职级大类(0A 1B 2C 3D 4P)
                .addField("A.id AS userPayApplyItemId")//id
                .queryMap();
        return sonlist;
    }

}
